import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:huxiaodui/api/model/mobile_app_model.dart';
import 'package:huxiaodui/config.dart';
import 'package:huxiaodui/store/store.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
import 'package:uuid/v4.dart';

class MyTopic {
  static const String _client = "GuardForce/MobileApp/{auth}/client";
  static const String _service = "GuardForce/MobileApp/{auth}/service";
  static const String _position = "GuardForce/MobileApp/{auth}/position";
  static const String _heart = "GuardForce/MobileApp/{auth}/heart";

  static String getClient(String auth) {
    log("_client $_client");
    return _client.replaceAll("{auth}", auth);
  }

  static String getPosition(String auth) {
    return _position.replaceAll("{auth}", auth);
  }

  static String getHeart(String auth) {
    return _heart.replaceAll("{auth}", auth);
  }

  static String getService(String auth) {
    return _service.replaceAll("{auth}", auth);
  }
}

class Subscribe {
  late String topic;
  late MqttQos qos;
  late Function(String) onBack;
  Subscribe(this.topic, this.qos, this.onBack);
}

class MQTT {
  /// 单例模式
  static final MQTT _instance = MQTT._internal();
  factory MQTT() {
    return _instance;
  }
  MQTT._internal() {
    Timer.periodic(const Duration(seconds: 5), (timer) async {
      if (client?.connectionStatus?.state == MqttConnectionState.disconnected ||
          client?.connectionStatus?.state == MqttConnectionState.faulted) {
        log("MQTT 尝试重新连接");
        await reconnect();
      } else if (client?.connectionStatus?.state ==
          MqttConnectionState.connected) {
      }
    });
  }

  MqttServerClient? client;
  Map<int, Subscribe> subscribes = {};

  Future<void> init() async {
    var clientIdentifier = await Store.mqtt.getClientIdentifier();

    client = MqttServerClient?.withPort(
        MqttConfig.server, clientIdentifier, MqttConfig.port);
    client?.connectionMessage = MqttConnectMessage()
        .authenticateAs(MqttConfig.username, MqttConfig.password);
  }

  ///初始化mqtt链接配置
  Future<bool> connect() async {
    try {
      client?.disconnect();
      await init();

      await client?.connect();

      //监听服务器发来的信息
      client?.updates?.listen((List<MqttReceivedMessage<MqttMessage>> c) {
        final MqttPublishMessage recMess = c[0].payload as MqttPublishMessage;
        //服务器返回的数据信息
        String pt =
            MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
        pt = utf8.decode(pt.runes.toList());
        //log("msg: $pt ");
        subscribes.forEach((key, value) {
          if (isTopicMatch(value.topic, c[0].topic)) {
            value.onBack(pt);
          }
        });
      });

      log('【MQTT】连接成功');
      return true;
    } catch (e) {
      return false;
    }
  }

  ///初始化mqtt链接配置
  Future<bool> reconnect() async {
    try {
      await connect().then((value) {
        if (value) {
          subscribes.forEach((key, value) {
            client?.subscribe(value.topic, value.qos);
            log('【MQTT】重新订阅成功 ${value.topic}');
          });
        }
      });
      return true;
    } catch (e) {
      return false;
    }
  }

  void subscribe(
      {
      /// 固定唯一标识
      required int id,

      ///订阅地址
      required String topic,
      MqttQos qos = MqttQos.atMostOnce,
      required Function(String) onMessage}) {
    MQTT().unsubscribe(id);
    subscribes[id] = Subscribe(topic, qos, onMessage);
    log("【MQTT】添加订阅 $topic");
    try {
      Subscription? res = client?.subscribe(topic, qos);
      log("【MQTT】订阅成功 ${res?.topic}");
    } catch (e) {}
  }

  void unsubscribe(int id) {
    Subscribe? subscribe = subscribes[id];

    if (subscribe != null) {
      try {
        client?.unsubscribe(subscribe.topic);
        subscribes.remove(id);
      } catch (_) {}
    }
  }

  void send(String topic, String? data) {
    try {
      MqttClientPayloadBuilder message = MqttClientPayloadBuilder();
      if (data != null) {
        message.addUTF8String(data);
      }
      client?.publishMessage(topic, MqttQos.exactlyOnce, message.payload!);

      log("【MQTT】发送 topic:$topic \n data:$data");
    } catch (e) {
      log("【MQTT】发送异常: ${e.toString()}");
    }
  }

  // 匹配Topic
  bool isTopicMatch(String topicFilter, String topic) {
    List<String> topicFilterLevels = topicFilter.split('/');
    List<String> topicLevels = topic.split('/');

    if (topicFilterLevels.length != topicLevels.length) {
      return false;
    }

    for (int i = 0; i < topicFilterLevels.length; i++) {
      String topicFilterLevel = topicFilterLevels[i];
      String topicLevel = topicLevels[i];

      if (topicFilterLevel == '+' || topicFilterLevel == '#') {
        continue;
      }

      if (topicFilterLevel != topicLevel) {
        return false;
      }
    }

    return true;
  }
}
